package net

import (
	"gamesdk/common/log"
	"gamesdk/lib/io"
	"net"
	"sync"
	"time"

	"github.com/gorilla/websocket"
)

/*
*处理链接
 */

const (
	g_HearBeat = 1 //心跳消息
)

/*
*定义一个逻辑接口
 */
type LogicInter interface {
	//初始化逻辑
	Init()
	RecvMsg(msg []byte)
	Exit()
	Error(error)
	HearBeat()
}

/*
*用户缓存
 */
type Manager struct {
	writeBuf  chan []byte
	readBuf   chan []byte
	timeout   int
	close     chan bool
	exit      bool
	ip        string
	heartbeat time.Duration //心跳时间
	webConn   *websocket.Conn
	tcpConn   net.Conn
	waitGroup sync.WaitGroup
	net       *Net
	model     Model
	logic     LogicInter
}

func NewWebManager(p *Net, conn *websocket.Conn, ip string, heartbeat int) *Manager {
	return &Manager{
		net:       p,
		webConn:   conn,
		timeout:   0,
		readBuf:   make(chan []byte, 1024),
		writeBuf:  make(chan []byte, 1024),
		close:     make(chan bool),
		exit:      false,
		ip:        ip,
		heartbeat: time.Duration(heartbeat) * time.Second,
		model:     WEB_SOCKET_MODEL,
	}
}
func NewTcpManager(p *Net, conn net.Conn, ip string, heartbeat int) *Manager {
	return &Manager{
		net:     p,
		tcpConn: conn,
		timeout: 0,
		//readBuf:   make(chan []byte, 1024),
		writeBuf:  make(chan []byte, 1024),
		close:     make(chan bool),
		exit:      false,
		ip:        ip,
		heartbeat: time.Duration(heartbeat) * time.Second,
		model:     TCP_MODEL,
	}
}

/*
*初始化服务
*参数说明:
*@param:reciveMsg   	接受消息回调函数
 */
func (this *Manager) Start() {
	log.Info("new connect %s", this.ip)
	this.exit = false
	this.logic.Init()
	go this.funcWork()
	this.funcRead()
	this.close <- true
	this.exit = true
	//关闭资源
	this.waitGroup.Wait()
	this.logic.Exit()
	close(this.close)
	//close(this.readBuf)
	close(this.writeBuf)
	log.Info("close connect %s", this.ip)
}

func (this *Manager) BindLogic(logic LogicInter) {
	this.logic = logic
}

/*
*启动写
 */
func (this *Manager) funcRead() {
	this.waitGroup.Add(1)
	defer this.waitGroup.Done()
	switch this.model {
	case WEB_SOCKET_MODEL:
		//webscoket模式
		for {
			message, err := io.WbRead(this.webConn)
			if err != nil {
				log.Error(err.Error())
				//关闭读写队列
				this.webConn.Close()
				return
			}
			this.logic.RecvMsg(message)
			this.webConn.SetReadDeadline(time.Now().Add(this.heartbeat * 2))

		}
	case TCP_MODEL:
		//tcp模式
		for {
			_, message, err := io.Read(this.tcpConn)
			if err != nil {
				log.Warn(err.Error())
				this.tcpConn.Close()
				//关闭读写队列
				return
			}
			this.logic.RecvMsg(message)
			this.tcpConn.SetReadDeadline(time.Now().Add(this.heartbeat * 2))

		}
	}
}

/*
*启动业务协程
 */
func (this *Manager) funcWork() {
	this.waitGroup.Add(1)
	defer this.waitGroup.Done()
	for {
		select {
		case msg := <-this.writeBuf:
			switch this.model {
			case WEB_SOCKET_MODEL:
				//webscoket模式
				err := io.WbWriteByTime(this.webConn, msg, time.Now().Add(this.heartbeat))
				if err != nil {
					log.Error(err.Error())
					this.webConn.Close()
				}
			case TCP_MODEL:
				//tcp模式
				_, err := io.WriteByTime(this.tcpConn, msg, time.Now().Add(this.heartbeat))
				if err != nil {
					log.Error(err.Error())
					this.tcpConn.Close()
				}
			}
		case <-time.After(this.heartbeat):
			log.Debug("msg:%s", "time out")
			this.Exit()
		case <-this.close:
			log.Debug("exit")
			return
		}

	}

}

func (this *Manager) Write(msg []byte) {
	if !this.exit {
		this.writeBuf <- msg
	}
}

func (this *Manager) GetIp() string {
	return this.ip
}

/*
*用户推出
 */
func (this *Manager) Exit() {
	switch this.model {
	case WEB_SOCKET_MODEL:
		//webscoket模式
		this.webConn.Close()
	case TCP_MODEL:
		//tcp模式
		this.tcpConn.Close()
	}
}
